#ifndef PHYSICALFIELD_H
#define PHYSICALFIELD_H

#include <vector>
#include <string>
#include <map>

#include "../Tool/Macros.h"
#include "../Input/PicParams.h"

class PicParams;
class Species;
class Projector;
class ParallelMPI;
class Solver;

template<class Type>
class Field;


class PhysicalField
{

public:
    PhysicalField( PicParams* params_, ParallelMPI* pmpi );

    virtual ~PhysicalField();

    virtual void incrementAvgFields(int itime);

    virtual void restartRhoJ();

    virtual void restartRhoJs(int ispec);

    virtual void computeTotalRhoJ();


    void initRhoJ(std::vector<Species*>& vecSpecies, Projector* Proj);

    bool isRhoNull(ParallelMPI* pmpi);

    //gather time-average fields to process 0 to output
    virtual void gatherAvgFields(ParallelMPI* pmpi);

    //gather fields to process 0 to calculate EM fields
    virtual void gatherFields(ParallelMPI* pmpi);

    Field<double>* Ex_;

    Field<double>* Ey_;

    Field<double>* Ez_;

    Field<double>* Bx_;

    Field<double>* By_;

    Field<double>* Bz_;

    Field<double>* rho_;

    Field<double>* phi_;

    Field<double>* rho_avg;

    Field<double>* phi_avg;

    Field<double>* Ex_avg;

    Field<double>* Ey_avg;

    Field<double>* Ez_avg;

    Field<double>* Bx_avg;

    Field<double>* By_avg;

    Field<double>* Bz_avg;

    Field<double>* rho_global;

    Field<double>* phi_global;

    Field<double>* Ex_global;

    Field<double>* Ey_global;

    Field<double>* Ez_global;



    Field<double>* rho_global_avg;

    Field<double>* phi_global_avg;

    Field<double>* Ex_global_avg;

    Field<double>* Ey_global_avg;


    std::vector<Field<double>*> allFields;

    std::vector<Field<double>*> allFields_avg;

    std::vector<Field<double>*> rho_s;
    std::vector<Field<double>*> rho_s_avg;
    std::vector<Field<double>*> rho_s_global;
    std::vector<Field<double>*> rho_s_global_avg;

    //Vector of macroscopic velocity and temperature
    //These fields are calculated in Diagnostic.run()
    std::vector<Field<double>*> Vx_s;
    std::vector<Field<double>*> Vx_s_avg;
    std::vector<Field<double>*> Vx_s_global;
    std::vector<Field<double>*> Vx_s_global_avg;

    std::vector<Field<double>*> Vy_s;
    std::vector<Field<double>*> Vy_s_avg;
    std::vector<Field<double>*> Vy_s_global;
    std::vector<Field<double>*> Vy_s_global_avg;

    std::vector<Field<double>*> Vz_s;
    std::vector<Field<double>*> Vz_s_avg;
    std::vector<Field<double>*> Vz_s_global;
    std::vector<Field<double>*> Vz_s_global_avg;

    std::vector<Field<double>*> Vp_s;
    std::vector<Field<double>*> Vp_s_avg;
    std::vector<Field<double>*> Vp_s_global;
    std::vector<Field<double>*> Vp_s_global_avg;

    std::vector<Field<double>*> T_s;
    std::vector<Field<double>*> T_s_avg;
    std::vector<Field<double>*> T_s_global;
    std::vector<Field<double>*> T_s_global_avg;

    std::vector<Field<double>*> Tx_s;
    std::vector<Field<double>*> Tx_s_avg;
    std::vector<Field<double>*> Tx_s_global;
    std::vector<Field<double>*> Tx_s_global_avg;

    std::vector<Field<double>*> Ty_s;
    std::vector<Field<double>*> Ty_s_avg;
    std::vector<Field<double>*> Ty_s_global;
    std::vector<Field<double>*> Ty_s_global_avg;

    std::vector<Field<double>*> Tz_s;
    std::vector<Field<double>*> Tz_s_avg;
    std::vector<Field<double>*> Tz_s_global;
    std::vector<Field<double>*> Tz_s_global_avg;

    //heat flux
    std::vector<Field<double>*> q_s;
    std::vector<Field<double>*> q_s_avg;
    std::vector<Field<double>*> q_s_global;
    std::vector<Field<double>*> q_s_global_avg;

    PicParams* params;

    ParallelMPI* pmpi;

    const int n_species;

    int dims_total;
    int dims_totalglobal;

    std::vector<SpeciesParameter> species_param;

protected:


private:


};

#endif
